package dbinfo

import (
	"encoding/json"
	"fmt"
	"reflect"
	"strconv"
	"strings"
	"time"
	"unicode/utf8"

	"gitee.com/tomatomeatman/golang-repository/bricks/model/emity"
)

// 数据信息注解
type DataInfo struct {
	GbDbField        bool   `json:"bDbField"`        //是否数据库字段
	GsName           string `json:"sName"`           //名称
	GsDbName         string `json:"sDbName"`         //所在数据库名称
	GsTableName      string `json:"sTableName"`      //所在数据库表表名称
	GsKeyName        string `json:"sKeyName"`        //表主键名称
	GiIndex          int    `json:"iIndex"`          //序号
	GiMaxLength      int    `json:"iMaxLength"`      //最大长度
	GbNull           bool   `json:"bNull"`           //是否允许为空
	Gbkey            bool   `json:"bkey"`            //是否主键
	GbExtra          bool   `json:"bExtra"`          //是否自增
	GsDefaultData    string `json:"sDefaultData"`    //默认值
	GsComment        string `json:"sComment"`        //字段备注
	GbDecimal        bool   `json:"bDecimal"`        //类型是否有小数
	GiIntegralLength int    `json:"iIntegralLength"` //整数位的长度
	GiDecimalLength  int    `json:"iDecimalLength"`  //小数位的长度
	GsDbFileType     string `json:"sDbFileType"`     //字段在数据库中的类型
	GsRelTitle       string `json:"sRelTitle"`       //关联后显示的名称
	GsRelName        string `json:"sRelName"`        //关联关系中被动关联的字段名,如 (LEFT JOIN RelTable ON RelTable.A = MainTable.B )中的A
	GsRelMainName    string `json:"sRelMainName"`    //关联关系中被关联的字段名,如 (LEFT JOIN RelTable ON RelTable.A = MainTable.B )中的B
}

// 创建结构体,并设置默认值
func (d *DataInfo) Now() *DataInfo {
	d.GbDbField = false    //是否数据库字段
	d.GsName = ""          //名称
	d.GsDbName = ""        //所在数据库名称
	d.GsTableName = ""     //所在数据库表表名称
	d.GsKeyName = ""       //表主键名称
	d.GiIndex = 0          //序号
	d.GiMaxLength = 1      //最大长度
	d.GbNull = true        //是否允许为空
	d.Gbkey = false        //是否主键
	d.GbExtra = false      //是否自增
	d.GsDefaultData = ""   //默认值
	d.GsComment = ""       //字段备注
	d.GbDecimal = false    //类型是否有小数
	d.GiIntegralLength = 0 //整数位的长度
	d.GiDecimalLength = 0  //小数位的长度
	d.GsDbFileType = ""    //字段在数据库中的类型
	d.GsRelTitle = ""      //关联后显示的名称
	d.GsRelName = ""       //关联关系中被动关联的字段名,如 (LEFT JOIN RelTable ON RelTable.A = MainTable.B )中的A
	d.GsRelMainName = ""   //关联关系中被关联的字段名,如 (LEFT JOIN RelTable ON RelTable.A = MainTable.B )中的B
	return d
}

// 取结构体指定属性的tag中的dataInfo信息
func (d DataInfo) GetDataInfoByName(entry interface{}, name string) *DataInfo {
	if name == "" {
		return nil
	}

	elem := reflect.TypeOf(entry).Elem() //通过反射获取type定义

	if sf, ok := elem.FieldByName(name); ok {
		str := sf.Tag.Get("dataInfo")
		if str == "" {
			return nil
		}

		var dataInfo DataInfo
		json.Unmarshal([]byte(str), &dataInfo)
		return &dataInfo
	}

	for i := 0; i < elem.NumField(); i++ {
		if !elem.Field(i).Anonymous {
			continue
		}

		temp := d.getAnonyTagInfoByName(elem.Field(i), name)
		if temp != "" {
			str := temp.Get("dataInfo")

			var dataInfo DataInfo
			json.Unmarshal([]byte(str), &dataInfo)
			return &dataInfo
		}
	}

	return nil
}

// 取结构体匿名属性中指定名称的tag信息
func (d DataInfo) getAnonyTagInfoByName(sf reflect.StructField, name string) reflect.StructTag {
	if !sf.Anonymous {
		return ""
	}

	t := sf.Type
	for k := 0; k < t.NumField(); k++ {
		if name == t.Field(k).Name {
			return t.Field(k).Tag
		}
	}

	for k := 0; k < t.NumField(); k++ {
		if !t.Field(k).Anonymous {
			continue
		}

		if t.Field(k).Anonymous {
			temp := d.getAnonyTagInfoByName(t.Field(k), name)
			if temp == "" {
				continue
			}

			return temp
		}
	}

	return ""
}

// 清除对象各个属性的值的前后空格
func (d DataInfo) TrimAttribute(entity interface{}) interface{} {
	rv := reflect.ValueOf(entity)      // 取得struct变量的指针
	s := reflect.TypeOf(entity).Elem() //通过反射获取type定义

	for i := 0; i < s.NumField(); i++ {
		//-- 匿名属性需要进一步向下探索 --//
		if s.Field(i).Anonymous {
			d.trimAttributeChild(s.Field(i), entity)
			continue
		}

		//--非匿名属性--//
		field := rv.Elem().FieldByName(s.Field(i).Name)
		vType := fmt.Sprintf("%v", field.Type())
		if !strings.Contains(vType, "string") {
			continue
		}

		oldValue := fmt.Sprintf("%v", reflect.ValueOf(field))
		if oldValue == "" {
			continue //如果值不为空,则不要赋值
		}

		field.SetString(strings.TrimSpace(oldValue))
	}

	return entity
}

// 清除匿名函数中字符串类型属性的值的前后空格
func (d DataInfo) trimAttributeChild(sf reflect.StructField, entity interface{}) {
	rv := reflect.ValueOf(entity) // 取得struct变量的指针
	t := sf.Type
	for k := 0; k < t.NumField(); k++ {
		if t.Field(k).Anonymous {
			d.trimAttributeChild(t.Field(k), entity)
			continue
		}

		field := rv.Elem().FieldByName(t.Field(k).Name)
		vType := fmt.Sprintf("%v", field.Type())
		if !strings.Contains(vType, "string") {
			continue
		}

		oldValue := fmt.Sprintf("%v", reflect.ValueOf(field))
		if oldValue == "" {
			continue //如果值不为空,则不要赋值
		}

		field.SetString(strings.TrimSpace(oldValue))
	}
}

/**
 * 用反射将map转成实体
 * data 数据
 * entity 数据结构
 */
func (d DataInfo) MapToEntity(data map[string]interface{}, entity interface{}) *emity.MsgEmity {
	if nil == data {
		return emity.MsgEmity{}.Err(1001, "数据为nil")
	}

	if nil == entity {
		return emity.MsgEmity{}.Err(1002, "数据结构为nil")
	}

	var rve reflect.Value
	typeOf := reflect.TypeOf(entity)  //通过反射获取type定义
	if typeOf.Kind() == reflect.Ptr { //是否指针类型
		rve = reflect.ValueOf(entity).Elem() // 取得struct变量的指针
	} else if typeOf.String() == "reflect.Value" {
		if entity.(reflect.Value).Kind() == reflect.Ptr {
			rve = entity.(reflect.Value).Elem()
		} else if entity.(reflect.Value).Kind() == reflect.Struct {
			rve = entity.(reflect.Value)
		} else {
			rve = entity.(reflect.Value)
		}
	} else {
		rve = reflect.ValueOf(entity)
	}

	for k, v := range data {
		field := rve.FieldByName("G" + k)
		field.Set(reflect.ValueOf(v))
	}

	return emity.MsgEmity{}.Success(entity, "设置结束")
}

/**
 * 对对象中添加了DataInfo注解的不为null的属性检查限制
 * data 数据
 * entity 检查用数据结构
 * ignoreNames 待忽略的字段
 */
func (d DataInfo) ValidAttr(data map[string]interface{}, entity interface{}, ignoreNames []string) *emity.MsgEmity {
	if nil == data {
		return emity.MsgEmity{}.Err(1001, "数据为nil")
	}

	if nil == entity {
		return emity.MsgEmity{}.Err(1002, "数据结构为nil")
	}

	dataMap := make(map[string]interface{}, len(data))
	for k, v := range data {
		dataMap["G"+k] = v
	}

	ignoreNamesMap := make(map[string]struct{}, len(ignoreNames))
	for _, v := range ignoreNames {
		ignoreNamesMap["G"+v] = struct{}{}
	}

	var s reflect.Type
	typeOf := reflect.TypeOf(entity) //通过反射获取type定义
	if typeOf.Kind() == reflect.Ptr {
		s = typeOf.Elem()
	} else if typeOf.String() == "reflect.Value" {
		if entity.(reflect.Value).Kind() == reflect.Ptr {
			s = entity.(reflect.Value).Elem().Type()
		} else if entity.(reflect.Value).Kind() == reflect.Struct {
			s = entity.(reflect.Value).Type()
		} else {
			s = entity.(reflect.Value).Type()
		}
	} else {
		s = typeOf
	}

	for i := 0; i < s.NumField(); i++ {
		_, ok := ignoreNamesMap[s.Field(i).Name]
		if ok {
			continue
		}

		//-- 匿名属性需要进一步向下探索 --//
		if s.Field(i).Anonymous {
			me := d.ValidAttr(dataMap, s.Field(i), ignoreNames)
			// me := service.validAttrChild(s.Field(i), dataMap, entity, ignoreNamesMap)
			if !me.Gsuccess {
				return me
			}

			continue
		}

		//--非匿名属性--//
		_, ok = dataMap[s.Field(i).Name]
		if !ok {
			continue //不存在此字段
		}

		str := s.Field(i).Tag.Get("dataInfo")
		if str == "" {
			continue
		}

		var dataInfo DataInfo
		json.Unmarshal([]byte(str), &dataInfo)

		oldValue := fmt.Sprintf("%v", dataMap[s.Field(i).Name])
		strType := dataInfo.GsDbFileType

		iL := dataInfo.GiMaxLength //真正存储字段的最大长度要求不可能小于1,否则无意义,如果定义iMaxLength为0,或-1则说明是要忽略检查的
		if !strings.Contains("/datetime/date/time/", strType) && iL > 0 && iL < utf8.RuneCountInString(oldValue) {
			return emity.MsgEmity{}.Err(1003, dataInfo.GsComment, "[", dataInfo.GsName, "]长度超出，最大长度限制为:", iL)
		}

		if !dataInfo.GbNull && oldValue == "<nil>" {
			return emity.MsgEmity{}.Err(1004, dataInfo.GsComment, "[", dataInfo.GsName, "]不允许为空！")
		}
	}

	return emity.MsgEmity{}.Success(1999, "验证通过")
}

// /**
//  * 对对象中添加了DataInfo注解的不为null的子属性检查限制
//  * sf 字段
//  * data 数据
//  * entity 检查用数据结构
//  * ignoreNames 待忽略的字段
//  */
// func (d DataInfo) validAttrChild(sf reflect.StructField, data map[string]interface{}, entity interface{}, ignoreNamesMap map[string]struct{}) *emity.MsgEmity {
// 	t := sf.Type

// 	for k := 0; k < t.NumField(); k++ {
// 		_, ok := ignoreNamesMap[t.Field(k).Name]
// 		if ok {
// 			continue
// 		}

// 		if t.Field(k).Anonymous {
// 			me := d.validAttrChild(t.Field(k), data, entity, ignoreNamesMap)
// 			if !me.Gsuccess {
// 				return me
// 			}

// 			continue
// 		}

// 		_, ok = data[t.Field(k).Name]
// 		if !ok {
// 			continue //不存在此字段
// 		}

// 		str := t.Field(k).Tag.Get("dataInfo")
// 		if str == "" {
// 			continue
// 		}

// 		var dataInfo DataInfo
// 		json.Unmarshal([]byte(str), &dataInfo)

// 		oldValue := strings.TrimSpace(fmt.Sprintf("%v", data[t.Field(k).Name]))
// 		strType := dataInfo.GsDbFileType

// 		iL := dataInfo.GiMaxLength //真正存储字段的最大长度要求不可能小于1,否则无意义,如果定义iMaxLength为0,或-1则说明是要忽略检查的
// 		if !strings.Contains("/datetime/date/time/", strType) && iL > 0 && iL < utf8.RuneCountInString(oldValue) {
// 			return emity.MsgEmity{}.Err(1005, dataInfo.GsComment, "[", dataInfo.GsName, "]长度超出，最大长度限制为:", iL)
// 		}

// 		if !dataInfo.GbNull && oldValue == "<nil>" {
// 			return emity.MsgEmity{}.Err(1006, dataInfo.GsComment, "[", dataInfo.GsName, "]不允许为空！")
// 		}
// 	}

// 	return emity.MsgEmity{}.Success(1999, "验证通过")
// }

/**
 * 对'新增'对象中添加了DataInfo注解的属性检查限制
 * entity 检查用数据结构
 * ignoreNames 待忽略的字段
 */
func (d DataInfo) ValidAttrByAdd(entity interface{}, ignoreNames []string) *emity.MsgEmity {
	if nil == entity {
		return emity.MsgEmity{}.Err(1001, "数据结构为nil")
	}

	ignoreNamesMap := make(map[string]struct{}, len(ignoreNames))
	for _, v := range ignoreNames {
		ignoreNamesMap["G"+v] = struct{}{}
	}

	var rve reflect.Value
	var s reflect.Type
	typeOf := reflect.TypeOf(entity)  //通过反射获取type定义
	if typeOf.Kind() == reflect.Ptr { //是否指针类型
		rve = reflect.ValueOf(entity).Elem() // 取得struct变量的指针
		s = reflect.TypeOf(entity).Elem()    //通过反射获取type定义
	} else if typeOf.String() == "reflect.Value" {
		if entity.(reflect.Value).Kind() == reflect.Ptr {
			rve = entity.(reflect.Value).Elem()
			s = rve.Type()
		} else if entity.(reflect.Value).Kind() == reflect.Struct {
			rve = entity.(reflect.Value)
			s = rve.Type()
		} else {
			rve = entity.(reflect.Value)
			s = rve.Type()
		}
	} else {
		rve = entity.(reflect.Value)
		s = rve.Type() //通过反射获取type定义
	}

	for i := 0; i < s.NumField(); i++ {
		//--非匿名属性--//
		if !s.Field(i).Anonymous {
			str := s.Field(i).Tag.Get("dataInfo")
			if str == "" {
				continue
			}

			var dataInfo DataInfo
			json.Unmarshal([]byte(str), &dataInfo)

			field := rve.FieldByName(s.Field(i).Name)
			oldValue := fmt.Sprintf("%v", reflect.ValueOf(field))
			strType := fmt.Sprintf("%v", field.Type()) //类型

			if strType == "int" { // 此时oldValue的值为:"<int Value>"
				oldValue = fmt.Sprintf("%v", field)
			}

			iL := dataInfo.GiMaxLength //真正存储字段的最大长度要求不可能小于1,否则无意义,如果定义iMaxLength为0,或-1则说明是要忽略检查的
			if !strings.Contains("/datetime/date/time/time.Time/decimal.Decimal/", strType) && iL > 0 && iL < utf8.RuneCountInString(oldValue) {
				return emity.MsgEmity{}.Err(1002, dataInfo.GsComment, "[", dataInfo.GsName, "]长度超出，最大长度限制为:", iL)
			}

			if !dataInfo.GbNull && ((oldValue == "<nil>") || (oldValue == "")) {
				return emity.MsgEmity{}.Err(1003, dataInfo.GsComment, "[", dataInfo.GsName, "]不允许为空！")
			}

			if strings.Contains("/datetime/date/time/time.Time/", strType) && !dataInfo.GbNull && (oldValue == "" || oldValue == "0001-01-01 00:00:00 +0000 UTC" || oldValue == "<nil>") {
				return emity.MsgEmity{}.Err(1004, dataInfo.GsComment, "[", dataInfo.GsName, "]不允许为空！")
			}

			if strings.Contains("/decimal.Decimal/*big.Float", strType) && (iL > 0) {
				str := fmt.Sprintf("%v", field)
				array := strings.Split(str, ".")

				if dataInfo.GiIntegralLength < len(array[0]) {
					return emity.MsgEmity{}.Err(1005, dataInfo.GsComment, "[", dataInfo.GsName, "]整数超出，最大长度限制为:", dataInfo.GiIntegralLength)
				}

				if (len(array) > 1) && (dataInfo.GiDecimalLength < len(array[1])) {
					return emity.MsgEmity{}.Err(1006, dataInfo.GsComment, "[", dataInfo.GsName, "]小数超过，最大长度限制为:", dataInfo.GiIntegralLength)
				}
			}

			if strings.Contains("/float64/float32/", strType) && (iL > 0) {
				str := fmt.Sprintf("%v", field)
				array := strings.Split(str, ".")

				if dataInfo.GiIntegralLength < len(array[0]) {
					return emity.MsgEmity{}.Err(1005, dataInfo.GsComment, "[", dataInfo.GsName, "]整数超出，最大长度限制为:", dataInfo.GiIntegralLength)
				}

				if (len(array) > 1) && (dataInfo.GiDecimalLength < len(array[1])) {
					return emity.MsgEmity{}.Err(1006, dataInfo.GsComment, "[", dataInfo.GsName, "]小数超过，最大长度限制为:", dataInfo.GiIntegralLength)
				}
			}

			continue
		}

		//-- 匿名属性需要进一步向下探索 --//
		anonyTagInfo := d.GetAnonyTagInfo(s.Field(i))
		if nil == anonyTagInfo {
			continue
		}

		for key := range anonyTagInfo {
			str := anonyTagInfo[key]
			if str == "" {
				continue
			}

			var dataInfo DataInfo
			json.Unmarshal([]byte(str), &dataInfo)

			field := rve.FieldByName(key)
			oldValue := fmt.Sprintf("%v", reflect.ValueOf(field))
			strType := fmt.Sprintf("%v", field.Type())

			if strType == "int" { // 此时oldValue的值为:"<int Value>"
				oldValue = fmt.Sprintf("%v", field)
			}

			iL := dataInfo.GiMaxLength //真正存储字段的最大长度要求不可能小于1,否则无意义,如果定义iMaxLength为0,或-1则说明是要忽略检查的
			if !strings.Contains("/datetime/date/time/time.Time/decimal.Decimal/", strType) && iL > 0 && iL < utf8.RuneCountInString(oldValue) {
				return emity.MsgEmity{}.Err(1002, dataInfo.GsComment, "[", dataInfo.GsName, "]长度超出，最大长度限制为:", iL)
			}

			if !dataInfo.GbNull && ((oldValue == "<nil>") || (oldValue == "")) {
				return emity.MsgEmity{}.Err(1003, dataInfo.GsComment, "[", dataInfo.GsName, "]不允许为空！")
			}

			if strings.Contains("/datetime/date/time/time.Time/", strType) && !dataInfo.GbNull && (oldValue == "" || oldValue == "0001-01-01 00:00:00 +0000 UTC" || oldValue == "<nil>") {
				return emity.MsgEmity{}.Err(1004, dataInfo.GsComment, "[", dataInfo.GsName, "]不允许为空！")
			}

			if strings.Contains("/decimal.Decimal/*big.Float", strType) && (iL > 0) {
				str := fmt.Sprintf("%v", field)
				array := strings.Split(str, ".")

				if dataInfo.GiIntegralLength < len(array[0]) {
					return emity.MsgEmity{}.Err(1005, dataInfo.GsComment, "[", dataInfo.GsName, "]整数超出，最大长度限制为:", dataInfo.GiIntegralLength)
				}

				if (len(array) > 1) && (dataInfo.GiDecimalLength < len(array[1])) {
					return emity.MsgEmity{}.Err(1006, dataInfo.GsComment, "[", dataInfo.GsName, "]小数超过，最大长度限制为:", dataInfo.GiIntegralLength)
				}
			}

			if strings.Contains("/float64/float32/", strType) && (iL > 0) {
				str := fmt.Sprintf("%v", field)
				array := strings.Split(str, ".")

				if dataInfo.GiIntegralLength < len(array[0]) {
					return emity.MsgEmity{}.Err(1007, dataInfo.GsComment, "[", dataInfo.GsName, "]整数超出，最大长度限制为:", dataInfo.GiIntegralLength)
				}

				if (len(array) > 1) && (dataInfo.GiDecimalLength < len(array[1])) {
					return emity.MsgEmity{}.Err(1008, dataInfo.GsComment, "[", dataInfo.GsName, "]小数超过，最大长度限制为:", dataInfo.GiIntegralLength)
				}
			}
		}
	}

	return emity.MsgEmity{}.Success(1999, "验证通过")
}

// /**
//  * 对'新增'对象中添加了DataInfo注解的子属性检查限制
//  * sf 字段
//  * entity 检查用数据结构
//  * ignoreNames 待忽略的字段
//  */
// func (d DataInfo) validAttrByAddChild(sf reflect.StructField, entity interface{}, ignoreNamesMap map[string]struct{}) *emity.MsgEmity {
// 	rv := reflect.ValueOf(entity) // 取得struct变量的指针

// 	t := sf.Type
// 	for k := 0; k < t.NumField(); k++ {
// 		_, ok := ignoreNamesMap[t.Field(k).Name]
// 		if ok {
// 			continue
// 		}

// 		if t.Field(k).Anonymous {
// 			me := d.validAttrByAddChild(t.Field(k), entity, ignoreNamesMap)
// 			if !me.Gsuccess {
// 				return me
// 			}

// 			continue
// 		}

// 		str := t.Field(k).Tag.Get("dataInfo")
// 		if str == "" {
// 			continue
// 		}

// 		var dataInfo DataInfo
// 		json.Unmarshal([]byte(str), &dataInfo)

// 		field := rv.Elem().FieldByName(t.Field(k).Name)
// 		oldValue := strings.TrimSpace(fmt.Sprintf("%v", reflect.ValueOf(field)))
// 		strType := fmt.Sprintf("%v", field.Type()) //类型

// 		iL := dataInfo.GiMaxLength //真正存储字段的最大长度要求不可能小于1,否则无意义,如果定义iMaxLength为0,或-1则说明是要忽略检查的
// 		if !strings.Contains("/datetime/date/time/time.Time/decimal.Decimal", strType) && iL > 0 && iL < utf8.RuneCountInString(oldValue) {
// 			return emity.MsgEmity{}.Err(1005, dataInfo.GsComment, "[", dataInfo.GsName, "]长度超出，最大长度限制为:", iL)
// 		}

// 		if !dataInfo.GbNull && (oldValue == "<nil>" || oldValue == "") {
// 			return emity.MsgEmity{}.Err(1006, dataInfo.GsComment, "[", dataInfo.GsName, "]不允许为空！")
// 		}

// 		if strings.Contains("/datetime/date/time/time.Time/", strType) && !dataInfo.GbNull && (oldValue == "" || oldValue == "0001-01-01 00:00:00 +0000 UTC" || oldValue == "<nil>") {
// 			return emity.MsgEmity{}.Err(1007, dataInfo.GsComment, "[", dataInfo.GsName, "]不允许为空！")
// 		}

// 		if strings.Contains("/decimal.Decimal/*big.Float", strType) && (iL > 0) {
// 			str := fmt.Sprintf("%v", field)
// 			array := strings.Split(str, ".")

// 			if dataInfo.GiIntegralLength < len(array[0]) {
// 				return emity.MsgEmity{}.Err(1008, dataInfo.GsComment, "[", dataInfo.GsName, "]整数超出，最大长度限制为:", dataInfo.GiIntegralLength)
// 			}

// 			if (len(array) > 1) && (dataInfo.GiDecimalLength < len(array[1])) {
// 				return emity.MsgEmity{}.Err(1009, dataInfo.GsComment, "[", dataInfo.GsName, "]小数超过，最大长度限制为:", dataInfo.GiIntegralLength)
// 			}
// 		}

// 		if strings.Contains("/float64/float32/", strType) && (iL > 0) {
// 			str := fmt.Sprintf("%v", field)
// 			array := strings.Split(str, ".")

// 			if dataInfo.GiIntegralLength < len(array[0]) {
// 				return emity.MsgEmity{}.Err(1008, dataInfo.GsComment, "[", dataInfo.GsName, "]整数超出，最大长度限制为:", dataInfo.GiIntegralLength)
// 			}

// 			if (len(array) > 1) && (dataInfo.GiDecimalLength < len(array[1])) {
// 				return emity.MsgEmity{}.Err(1009, dataInfo.GsComment, "[", dataInfo.GsName, "]小数超过，最大长度限制为:", dataInfo.GiIntegralLength)
// 			}
// 		}
// 	}

// 	return emity.MsgEmity{}.Success(1999, "验证通过")
// }

/**
 * 对'编辑'对象中添加了DataInfo注解的不为null的属性检查限制
 * data 数据
 * entity 检查用数据结构
 * ignoreNames 待忽略的字段
 */
func (d DataInfo) ValidAttrByEdit(data map[string]interface{}, entity interface{}, ignoreNames []string) *emity.MsgEmity {
	if nil == data {
		return emity.MsgEmity{}.Err(1001, "数据为nil")
	}

	if nil == entity {
		return emity.MsgEmity{}.Err(1002, "数据结构为nil")
	}

	dataMap := make(map[string]interface{}, len(data))
	for k, v := range data {
		dataMap["G"+k] = v
	}

	ignoreNamesMap := make(map[string]struct{}, len(ignoreNames))
	for _, v := range ignoreNames {
		ignoreNamesMap["G"+v] = struct{}{}
	}

	//rv := reflect.ValueOf(entity)      // 取得struct变量的指针
	s := reflect.TypeOf(entity).Elem() //通过反射获取type定义

	for i := 0; i < s.NumField(); i++ {
		_, ok := ignoreNamesMap[s.Field(i).Name]
		if ok {
			continue
		}

		//-- 匿名属性需要进一步向下探索 --//
		if s.Field(i).Anonymous {
			me := d.validAttrByEditChild(s.Field(i), dataMap, entity, ignoreNamesMap)
			if !me.Gsuccess {
				return me
			}

			continue
		}

		//--非匿名属性--//
		_, ok = dataMap[s.Field(i).Name]
		if !ok {
			continue //不存在此字段
		}

		str := s.Field(i).Tag.Get("dataInfo")
		if str == "" {
			continue
		}

		var dataInfo DataInfo
		json.Unmarshal([]byte(str), &dataInfo)

		// field := rv.Elem().FieldByName(s.Field(i).Name)
		// oldValue := fmt.Sprintf("%v", reflect.ValueOf(field))
		// strType := fmt.Sprintf("%v", field.Type()) //类型

		oldValue := strings.TrimSpace(fmt.Sprintf("%v", dataMap[s.Field(i).Name]))
		strType := dataInfo.GsDbFileType

		iL := dataInfo.GiMaxLength //真正存储字段的最大长度要求不可能小于1,否则无意义,如果定义iMaxLength为0,或-1则说明是要忽略检查的
		if !strings.Contains("/datetime/date/time/time.Time/decimal.Decimal", strType) && iL > 0 && iL < utf8.RuneCountInString(oldValue) {
			return emity.MsgEmity{}.Err(1003, dataInfo.GsComment, "[", dataInfo.GsName, "]长度超出，最大长度限制为:", iL)
		}

		if !dataInfo.GbNull && (oldValue == "<nil>" || oldValue == "") {
			return emity.MsgEmity{}.Err(1004, dataInfo.GsComment, "[", dataInfo.GsName, "]不允许为空！")
		}

		if strings.Contains("/decimal.Decimal/*big.Float", strType) && (iL > 0) {
			str := fmt.Sprintf("%v", dataMap[s.Field(i).Name])
			array := strings.Split(str, ".")

			if dataInfo.GiIntegralLength < len(array[0]) {
				return emity.MsgEmity{}.Err(1005, dataInfo.GsComment, "[", dataInfo.GsName, "]整数超出，最大长度限制为:", dataInfo.GiIntegralLength)
			}

			if (len(array) > 1) && (dataInfo.GiDecimalLength < len(array[1])) {
				return emity.MsgEmity{}.Err(1006, dataInfo.GsComment, "[", dataInfo.GsName, "]小数超过，最大长度限制为:", dataInfo.GiIntegralLength)
			}
		}

		if strings.Contains("/float64/float32/", strType) && (iL > 0) {
			str := fmt.Sprintf("%f", dataMap[s.Field(i).Name])
			array := strings.Split(str, ".")

			if dataInfo.GiIntegralLength < len(array[0]) {
				return emity.MsgEmity{}.Err(1005, dataInfo.GsComment, "[", dataInfo.GsName, "]整数超出，最大长度限制为:", dataInfo.GiIntegralLength)
			}

			if (len(array) > 1) && (dataInfo.GiDecimalLength < len(array[1])) {
				return emity.MsgEmity{}.Err(1006, dataInfo.GsComment, "[", dataInfo.GsName, "]小数超过，最大长度限制为:", dataInfo.GiIntegralLength)
			}
		}
	}

	return emity.MsgEmity{}.Success(1999, "验证通过")
}

/**
 * 对'编辑'对象中添加了DataInfo注解的不为null的子属性检查限制
 * sf 字段
 * data 数据
 * entity 检查用数据结构
 * ignoreNames 待忽略的字段
 */
func (d DataInfo) validAttrByEditChild(sf reflect.StructField, data map[string]interface{}, entity interface{}, ignoreNamesMap map[string]struct{}) *emity.MsgEmity {
	//rv := reflect.ValueOf(entity) // 取得struct变量的指针

	t := sf.Type
	for k := 0; k < t.NumField(); k++ {
		_, ok := ignoreNamesMap[t.Field(k).Name]
		if ok {
			continue
		}

		if t.Field(k).Anonymous {
			me := d.validAttrByEditChild(t.Field(k), data, entity, ignoreNamesMap)
			if !me.Gsuccess {
				return me
			}

			continue
		}

		_, ok = data[t.Field(k).Name]
		if !ok {
			continue //不存在此字段
		}

		str := t.Field(k).Tag.Get("dataInfo")
		if str == "" {
			continue
		}

		var dataInfo DataInfo
		json.Unmarshal([]byte(str), &dataInfo)

		// field := rv.Elem().FieldByName(t.Field(k).Name)
		// oldValue := fmt.Sprintf("%v", reflect.ValueOf(field))
		// strType := fmt.Sprintf("%v", field.Type()) //类型

		oldValue := strings.TrimSpace(fmt.Sprintf("%v", data[t.Field(k).Name]))
		strType := dataInfo.GsDbFileType

		iL := dataInfo.GiMaxLength //真正存储字段的最大长度要求不可能小于1,否则无意义,如果定义iMaxLength为0,或-1则说明是要忽略检查的
		if !strings.Contains("/datetime/date/time/", strType) && iL > 0 && iL < utf8.RuneCountInString(oldValue) {
			return emity.MsgEmity{}.Err(1005, dataInfo.GsComment, "[", dataInfo.GsName, "]长度超出，最大长度限制为:", iL)
		}

		if !dataInfo.GbNull && (oldValue == "<nil>" || oldValue == "") {
			return emity.MsgEmity{}.Err(1006, dataInfo.GsComment, "[", dataInfo.GsName, "]不允许为空！")
		}

		// if strings.Contains("/string/varchar/longtext/tinytext/text/", strType) && !dataInfo.GbNull && oldValue == "<nil>" {
		// 	return emity.MsgEmity{}.Err(1005, dataInfo.GsComment, "[", dataInfo.GsName, "]不允许为空！")
		// }

		// if strings.Contains("/datetime/date/time/", strType) && !dataInfo.GbNull && ("" != oldValue || oldValue == "0001-01-01 00:00:00 +0000 UTC") {
		// 	return emity.MsgEmity{}.Err(1006, dataInfo.GsComment, "[", dataInfo.GsName, "]不允许为空！")
		// }
	}

	return emity.MsgEmity{}.Success(1999, "验证通过")
}

// /**
//  * 对对象中添加了DataInfo注解的不为null的属性检查限制
//  * data 数据
//  * entity 数据结构
//  * ignoreNames 待忽略的字段
//  */
// func (d DataInfo) ValidAttrByAdd(data map[string]interface{}, entity interface{}, ignoreNames []string) *emity.MsgEmity {
// 	if nil == entity {
// 		return emity.MsgEmity{}.Err(1001, "数据为null")
// 	}

// 	ignoreNamesMap := make(map[string]struct{}, len(ignoreNames))
// 	for _, v := range ignoreNames {
// 		ignoreNamesMap["G"+v] = struct{}{}
// 	}

// 	rv := reflect.ValueOf(entity)      // 取得struct变量的指针
// 	s := reflect.TypeOf(entity).Elem() //通过反射获取type定义

// 	for i := 0; i < s.NumField(); i++ {
// 		_, ok := ignoreNamesMap[s.Field(i).Name]
// 		if ok {
// 			continue
// 		}

// 		//-- 匿名属性需要进一步向下探索 --//
// 		if s.Field(i).Anonymous {
// 			me := d.validAttrByAddChild(s.Field(i), entity, ignoreNamesMap)
// 			if !me.Gsuccess {
// 				return me
// 			}

// 			continue
// 		}

// 		//--非匿名属性--//
// 		_, ok = data[s.Field(i).Name]
// 		if !ok {
// 			continue//不存在此字段
// 		}

// 		str := s.Field(i).Tag.Get("dataInfo")
// 		if str == "" {
// 			continue
// 		}

// 		field := rv.Elem().FieldByName(s.Field(i).Name)
// 		oldValue := fmt.Sprintf("%v", reflect.ValueOf(field))

// 		var dataInfo DataInfo
// 		json.Unmarshal([]byte(str), &dataInfo)

// 		strType := fmt.Sprintf("%v", field.Type()) //类型

// 		iL := dataInfo.GiMaxLength //真正存储字段的最大长度要求不可能小于1,否则无意义,如果定义iMaxLength为0,或-1则说明是要忽略检查的
// 		if iL > 0 && iL < utf8.RuneCountInString(oldValue) && !strings.Contains(strType, "time.Time") {
// 			return emity.MsgEmity{}.Err(1002, dataInfo.GsComment, "[", dataInfo.GsName, "]长度超出，最大长度限制为:", iL)
// 		}

// 		if !dataInfo.GbNull && "" == strings.TrimSpace(oldValue) {
// 			return emity.MsgEmity{}.Err(1003, dataInfo.GsComment, "[", dataInfo.GsName, "]不允许为空！")
// 		}
// 	}

// 	return emity.MsgEmity{}.Success(1999, "验证通过")
// }

// /**
//  * 对对象中添加了DataInfo注解的不为null的子属性检查限制
//  * sf 字段
//  * data 数据
//  * entity 数据结构
//  * ignoreNames 待忽略的字段
//  */
// func (d DataInfo) validAttrByAddChild(sf reflect.StructField, data map[string]interface{}, entity interface{}, ignoreNamesMap map[string]struct{}) *emity.MsgEmity {
// 	//rv := reflect.ValueOf(entity) // 取得struct变量的指针

// 	t := sf.Type
// 	for k := 0; k < t.NumField(); k++ {
// 		_, ok := ignoreNamesMap[t.Field(k).Name]
// 		if ok {
// 			continue
// 		}

// 		if t.Field(k).Anonymous {
// 			me := d.validAttrByAddChild(t.Field(k), data, entity, ignoreNamesMap)
// 			if !me.Gsuccess {
// 				return me
// 			}

// 			continue
// 		}

// 		_, ok = data[t.Field(k).Name]
// 		if !ok {
// 			continue//不存在此字段
// 		}

// 		str := t.Field(k).Tag.Get("dataInfo")
// 		if str == "" {
// 			continue
// 		}

// 		//field := rv.Elem().FieldByName(t.Field(k).Name)
// 		//oldValue := fmt.Sprintf("%v", reflect.ValueOf(field))
// 		oldValue := fmt.Sprintf("%v", reflect.ValueOf(data[t.Field(k).Name]))

// 		var dataInfo DataInfo
// 		json.Unmarshal([]byte(str), &dataInfo)

// 		strType := fmt.Sprintf("%v", field.Type()) //类型

// 		iL := dataInfo.GiMaxLength //真正存储字段的最大长度要求不可能小于1,否则无意义,如果定义iMaxLength为0,或-1则说明是要忽略检查的
// 		if !strings.Contains(strType, "time.Time") && iL > 0 && iL < utf8.RuneCountInString(oldValue) {
// 			return emity.MsgEmity{}.Err(1004, dataInfo.GsComment, "[", dataInfo.GsName, "]长度超出，最大长度限制为:", iL)
// 		}

// 		if strings.Contains(strType, "string") && !dataInfo.GbNull && "" == strings.TrimSpace(oldValue) {
// 			return emity.MsgEmity{}.Err(1005, dataInfo.GsComment, "[", dataInfo.GsName, "]不允许为空！")
// 		}

// 		if strings.Contains(strType, "time.Time") && !dataInfo.GbNull && ("" != strings.TrimSpace(oldValue) || "0001-01-01 00:00:00 +0000 UTC" == reflect.ValueOf(field).String()) {
// 			return emity.MsgEmity{}.Err(1006, dataInfo.GsComment, "[", dataInfo.GsName, "]不允许为空！")
// 		}
// 	}

// 	return emity.MsgEmity{}.Success(1999, "验证通过")
// }

// 对对象中添加了dataInfo注解的属性添加默认值
func (d DataInfo) SetDataInfoDefault(entity interface{}) interface{} {
	//rv := reflect.ValueOf(entity)      // 取得struct变量的指针
	//s := reflect.TypeOf(entity).Elem() //通过反射获取type定义

	var rve reflect.Value
	var s reflect.Type
	typeOf := reflect.TypeOf(entity)  //通过反射获取type定义
	if typeOf.Kind() == reflect.Ptr { //是否指针类型
		rve = reflect.ValueOf(entity).Elem() // 取得struct变量的指针
		s = reflect.TypeOf(entity).Elem()    //通过反射获取type定义
	} else if typeOf.String() == "reflect.Value" {
		if entity.(reflect.Value).Kind() == reflect.Ptr {
			rve = entity.(reflect.Value).Elem()
			s = entity.(reflect.Value).Elem().Type()
		} else if entity.(reflect.Value).Kind() == reflect.Struct {
			rve = entity.(reflect.Value)
			s = entity.(reflect.Value).Type()
		} else {
			rve = entity.(reflect.Value)
			s = entity.(reflect.Value).Type()
		}
	} else {
		rve = entity.(reflect.Value)
		s = entity.(reflect.Value).Type() //通过反射获取type定义
	}

	for i := 0; i < s.NumField(); i++ {
		//--非匿名属性--//
		if !s.Field(i).Anonymous {
			field := rve.FieldByName(s.Field(i).Name)

			oldValue := reflect.ValueOf(field)
			if fmt.Sprintf("%v", oldValue) != "" {
				continue //如果值不为空,则不要赋值
			}

			str := s.Field(i).Tag.Get("dataInfo")
			if str == "" {
				continue
			}

			var dataInfo DataInfo
			json.Unmarshal([]byte(str), &dataInfo)

			strType := fmt.Sprintf("%v", field.Type())
			if strings.Contains(strType, "string") {
				field.SetString(dataInfo.GsDefaultData)
			} else if strings.Contains(strType, "time.Time") {
				field.Set(reflect.ValueOf(time.Now()))
			} else if strings.Contains(strType, "int") {
				//value, err := strconv.Atoi(dataInfo.GsDefaultData)
				value, err := strconv.ParseInt(dataInfo.GsDefaultData, 8, 32)
				if err == nil {
					field.SetInt(value)
				}
			} else if strings.Contains(strType, "int64") {
				value, err := strconv.ParseInt(dataInfo.GsDefaultData, 10, 64)
				if err == nil {
					field.SetInt(value)
				}
			}

			continue
		}

		//-- 匿名属性需要进一步向下探索 --//
		anonyTagInfo := d.GetAnonyTagInfo(s.Field(i))
		if nil == anonyTagInfo {
			continue
		}

		for key := range anonyTagInfo {
			field := rve.FieldByName(key)

			oldValue := reflect.ValueOf(field)
			if fmt.Sprintf("%v", oldValue) != "" {
				continue //如果值不为空,则不要赋值
			}
			str := anonyTagInfo[key]
			if str == "" {
				continue
			}

			var dataInfo DataInfo
			json.Unmarshal([]byte(str), &dataInfo)

			strType := fmt.Sprintf("%v", field.Type())
			if strings.Contains(strType, "string") {
				field.SetString(dataInfo.GsDefaultData)
			} else if strings.Contains(strType, "time.Time") {
				field.Set(reflect.ValueOf(time.Now()))
			} else if strings.Contains(strType, "int") {
				//value, err := strconv.Atoi(dataInfo.GsDefaultData)
				value, err := strconv.ParseInt(dataInfo.GsDefaultData, 8, 32)
				if err == nil {
					field.SetInt(value)
				}
			} else if strings.Contains(strType, "int64") {
				value, err := strconv.ParseInt(dataInfo.GsDefaultData, 10, 64)
				if err == nil {
					field.SetInt(value)
				}
			}
		}
	}

	return entity
}

// 取匿名属性Tag信息
func (d DataInfo) GetAnonyTagInfo(sf reflect.StructField) map[string]string {
	if !sf.Anonymous {
		return nil
	}

	result := make(map[string]string)
	t := sf.Type
	for k := 0; k < t.NumField(); k++ {
		if t.Field(k).Anonymous {
			temp := d.GetAnonyTagInfo(t.Field(k))
			if nil == temp {
				continue
			}

			for key := range temp {
				result[key] = temp[key]
			}

			continue
		}

		tag := t.Field(k).Tag
		result[t.Field(k).Name] = tag.Get("dataInfo")
	}

	return result
}
